/* Regex.h
 *
 *  Author: Bematech S.A.
 */

#ifndef __BILBAO_UTIL_REGEX_CLASS_H__
#define __BILBAO_UTIL_REGEX_CLASS_H__

#include "bilbao/types.h"

/**
 * RegexPair é um std::pair contendo o par de valores: o primeiro valor indica a
 * posição inicial da ocorrência da expressão regular na string e o segundo valor
 * indica a posição final.
 */
#define RegexPair std::pair<regoff_t, regoff_t>

/**
 * REGEX_SERIAL_COMMAND é uma string contendo a expressão regular para verificação
 * de um comando serial.
 */
#define REGEX_SERIAL_COMMAND	"<ESC.(00|99|I[0-9]{4}|F[0-9]{4})>"

/**
 * REGEX_ESC00 é uma string contendo a expressão regular para verificação do
 * comando ESC00.
 * Por exemplo: '<ESC.00>123456'.
 */
#define REGEX_ESC00			"<ESC.00>[0-9]{6}"

/**
 * REGEX_ESC99 é uma string contendo a expressão regular para verificação do
 * comando ESC99.
 * Por exemplo: '<ESC.99>1234560001'.
 */
#define REGEX_ESC99			"<ESC.99>[0-9]{6}[0-9]{4}"

/**
 * REGEX_ESCI é uma string contendo a expressão regular para verificação do
 * comando ESCI.
 * Por exemplo: '<ESC.I0001>'.
 */
#define REGEX_ESCI			"<ESC.I[0-9]{4}>"

/**
 * REGEX_ESCF é uma string contendo a expressão regular para verificação do
 * comando ESCF.
 * Por exemplo: '<ESC.F0001>'.
 */
#define REGEX_ESCF			"<ESC.F[0-9]{4}>"

/** TODO: Analisar as macros abaixo.
#define IS_SERIAL_COMMAND(REGEX, REG_PAIR, MSG) \
			REGEX.match(REG_PAIR, SERIAL_COMMAND, MSG)
#define IS_ESC00(REGEX, REG_PAIR, MSG) \
			REGEX.match(REG_PAIR, ESC00, MSG)
#define IS_ESC99(REGEX, REG_PAIR, MSG) \
			REGEX.match(REG_PAIR, ESC99, MSG)
#define IS_ESCI(REGEX, REG_PAIR, MSG) \
			REGEX.match(REG_PAIR, ESCI, MSG)
#define IS_ESCF(REGEX, REG_PAIR, MSG) \
			REGEX.match(REG_PAIR, ESCF, MSG)
*/

namespace bilbao
{
	namespace util
	{
		/**
		 * Classe responsável para localização das ocorrências de uma expressão
		 * regular em uma string.
		 * O processo para verificação de uma expressão regular é feita da seguinte
		 * maneira:
		 *   - É passado a expressão regular;
		 *   - É passado um texto que será buscado a expressão regular;
		 *   - Se for achado uma ocorrência da expressão regular no texto, é
		 *     retornado um par de valores contendo a posição inicial no texto
		 *     da ocorrência e a posição final.
		 */
		class Regex
		{
		public:
			/**
			 * Construtor Padrão
			 */
			Regex( void );

			/**
			 * Realiza uma única busca de uma expressão regular na mensagem
			 * recebida. O retorno dar-se através do parâmetro <i>result</i>
			 * recebido que corresponde ao par das posições, início e fim, da
			 * mensagem. Se for encontrado alguma ocorrência, é retornado o par
			 * contendo as posições. Caso contrário, o par será preenchido com o
			 * valor -1, ou seja, <-1,-1>.
			 *
			 * @param	result				- Par das posições da ocorrência da mensagem
			 * 			regularExpression	- Expressão regular que será buscada
			 * 			message				- Texto onde será buscada a ocorrência da expressão regular
			 * @return	O retorno da função é o código do erro, caso ocorra algum.
			 */
			int match( RegexPair& result,
					   const char* regularExpression,
					   const char* message );

			/**
			 * Realiza a busca de várias ocorrências de uma expressão regular na
			 * mensagem recebida. O retorno dar-se através do parâmetro <i>result</i>
			 * recebido que corresponde ao par das posições, início e fim, da
			 * mensagem e da própria função. Se for encontrado alguma ocorrência,
			 * é retornado os pares contendo as posições, preenchidas no vetor,
			 * e o tamanho do vetor. Caso contrário, a função retorna 0, ou seja,
			 * o tamanho do vetor de ocorrências.
			 *
			 * @param	result				- Par das posições da ocorrência da mensagem
			 * 			regularExpression	- Expressão regular que será buscada
			 * 			message				- Texto onde será buscada a ocorrência da expressão regular
			 * @return	O retorno da função é tamanho do vetor das posições
			 */
			int allMatch( std::vector<RegexPair>& result,
					      const char* regularExpression,
					      const char* message );

			/**
			 * Sobrecarga do método <i>void getError( int code, char* buffer );</i>.
			 * Procedimento que retorna a mensagem correspondente ao código do
			 * erro ocorrido na última verificação da ocorrência de uma expressão
			 * regular num texto. O retorno dar-se através do parâmetro <i>buffer</i>
			 * recebido na função.
			 *
			 * @param	buffer	- Mensagem correspondente ao erro
			 */
			void getError( char* buffer );

			/**
			 * Destrutor
			 */
			virtual ~Regex( void );

		private:
			/**
			 * Usado para armazenamento temporário da expressão regular
			 */
			regex_t _regex;

			/**
			 * Usado para busca de uma expressão regular em um texto
			 */
			regmatch_t _match;

			/**
			 * Usado para preservar o erro da última operação realizada
			 */
			int _errorCode;

			/**
			 * Procedimento que retorna a mensagem correspondente ao código do
			 * erro ocorrido no momento da verificação da ocorrência de uma expr
			 * essão regular num texto. O retorno dar-se através do parâmetro
			 * <i>buffer</i> recebido na função.
			 *
			 * @param	code	- Código do erro
			 * 			buffer	- Mensagem correspondente ao erro
			 */
			void getError( int code, char* buffer );

			/**
			 * Construtor de cópia
			 */
			Regex( const Regex& );
			
			/**
			 * Operador de cópia
			 */
			Regex& operator=( const Regex& );

		};
	} //namespace util
} //namespace bilbao

#endif //__BILBAO_UTIL_REGEX_CLASS_H__
